#define PrynInternal
#define PrynImplementation
#include "platform.h"

HINSTANCE prynStateInstance = 0;

PrynBaseLibraryEntryPoint (void *instance)
{
	prynStateInstance = instance;
}

#ifdef __DMC__ /* DigitalMars C Compiler */
#pragma startaddress (_DllMainCRTStartup)
#endif /* __DMC__ */

#ifndef IS_INTRESOURCE
#define IS_INTRESOURCE(VALUE) ((uintptr_t) (VALUE) < 65536)
#endif /* IS_INTRESOURCE */

#ifndef LONG_PTR
#define LONG_PTR uintptr_t
#endif /* LONG_PTR */

BOOL CALLBACK eachResource (HMODULE hModule, LPCSTR lpszType, LPSTR lpszName, PrynState *state)
{
	prynPrintStringLiteral (state, "Resource: ");
	if (IS_INTRESOURCE (lpszType))
		prynPrintInteger (state, (int) lpszType);
	else
		prynPrintFormat (state, "'%s'", lpszType);
	prynPrintStringLiteral (state, " ");
	if (IS_INTRESOURCE (lpszName))
		prynPrintInteger (state, (int) lpszName);
	else
		prynPrintFormat (state, "'%s'", lpszName);
	prynPrintStringLiteral (state, "\n");
	return 1;
}

void listResources (HANDLE library, char *type, PrynState *state)
{
	if (!EnumResourceNamesA (library, type, (ENUMRESNAMEPROC) &eachResource, (unsigned int) state))
		prynPrintFormat (state, "What? %d\n", type);
}

static BOOL CALLBACK eachResourceType (HMODULE module, LPSTR lpszType, PrynState *state)
{
	prynPrintFormat (state, "Type: ");
	if (IS_INTRESOURCE (lpszType))
		prynPrintInteger (state, (int) lpszType);
	else
		prynPrintFormat (state, "'%s'", lpszType);
	prynPrintFormat (state, "\n");
	listResources (module, lpszType, state);
	//listProperties (hModule, lpszType);
	return 1;
}

typedef struct ResourceString ResourceString;

struct ResourceString
{
	PrynResourceIndex index;
	PrynString string;
	ResourceString *next;
};

ResourceString *firstResourceString = 0;

PrynExport (PrynResult, prynStateResourceString, (PrynState *state, PrynResourceIndex index, PrynString *output))
{
	PrynStartFunctionHasState ();
	ResourceString *string;
	char buffer [1024];
	int length;

	if (output) prynStringNull (output);
	prynAssert (state && output, NullArgument);

	for (string = firstResourceString; string; string = string->next)
		if (string->index == index)
		{
			*output = string->string;
			prynReturnSuccess ();
		}
	
	length = LoadStringA (prynStateInstance, index, buffer, sizeof (buffer));
	
	if (length == 0)
	{
		prynStringLiteral (output, "Could not find resource in DLL.");
		prynReturnFailure (Failure);
	}
	
	if ((result = prynAllocate (state, sizeof (ResourceString) + length + 1, (void **) &string)) < 0)
	{
		prynStringLiteral (output, "Could not allocate memory for resource string.");
		goto failure;
	}

	string->index = index;
	prynStringFrom (&string->string, (char *) (&string->next + 1), length);
	string->next = firstResourceString;
	prynCopyMemory (string->string.pointer, buffer, length + 1);
	firstResourceString = string;
	*output = string->string;
	PrynEndFunction ();
}
